// Game.h : Declaration of the CGame

#ifndef __Game_H_
#define __Game_H_

#include "resource.h"       // main symbols
#include <atlctl.h>
#include <comdef.h>


#include "ASpriteCECP.h"
#include "gx.h"
#include "CSpriteLow.h"
#include "CSpriteHigh.h"
#include "CWaveOut.h"
#include "TimerCustom.h"



void HRVERIFY(HRESULT hr, char * msg);
extern const GUID CLSID_VBScript;


// ID for the timer
#define ASPRITE_TIMER 69
#define MAX_DYNAMIC_SPRITES 1024
#define MAX_SOUNDS 128
#define MAX_TIMERS 128

#define MAX_TILES_X		256
#define MAX_TILES_Y		256
#define MAX_TILES_COLLISION 128

/////////////////////////////////////////////////////////////////////////////
// CGame
class ATL_NO_VTABLE CGame : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public IDispatchImpl<IGame, &IID_IGame, &LIBID_ASPRITECELib>,
	public CComControl<CGame>,
	public IPersistStreamInitImpl<CGame>,
	public IOleControlImpl<CGame>,
	public IOleObjectImpl<CGame>,
	public IOleInPlaceActiveObjectImpl<CGame>,
	public IViewObjectExImpl<CGame>,
	public IOleInPlaceObjectWindowlessImpl<CGame>,
	public IConnectionPointContainerImpl<CGame>,
	public IPersistStorageImpl<CGame>,
	public ISpecifyPropertyPagesImpl<CGame>,
	public IQuickActivateImpl<CGame>,
	public IDataObjectImpl<CGame>,
	public IProvideClassInfo2Impl<&CLSID_Game, &DIID__IGameEvents, &LIBID_ASPRITECELib>,
	public IPropertyNotifySinkCP<CGame>,
	public CComCoClass<CGame, &CLSID_Game>,
	public CProxy_IGameEvents< CGame >
{
public:
	CGame()
	{
		DoInit();
		m_bAutoFullScreen=FALSE;

		m_this = this;
	}

DECLARE_REGISTRY_RESOURCEID(IDR_Game)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CGame)
	COM_INTERFACE_ENTRY(IGame)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IViewObjectEx)
	COM_INTERFACE_ENTRY(IViewObject2)
	COM_INTERFACE_ENTRY(IViewObject)
	COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
	COM_INTERFACE_ENTRY(IOleInPlaceObject)
	COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
	COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
	COM_INTERFACE_ENTRY(IOleControl)
	COM_INTERFACE_ENTRY(IOleObject)
	COM_INTERFACE_ENTRY(IPersistStreamInit)
	COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
	COM_INTERFACE_ENTRY(IConnectionPointContainer)
	COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
	COM_INTERFACE_ENTRY(IQuickActivate)
	COM_INTERFACE_ENTRY(IPersistStorage)
	COM_INTERFACE_ENTRY(IDataObject)
	COM_INTERFACE_ENTRY(IProvideClassInfo)
	COM_INTERFACE_ENTRY(IProvideClassInfo2)
	COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()

BEGIN_PROP_MAP(CGame)
	PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
	PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
	// Example entries
	// PROP_ENTRY("Property Description", dispid, clsid)
	// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()

BEGIN_CONNECTION_POINT_MAP(CGame)
	CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
	CONNECTION_POINT_ENTRY(DIID__IGameEvents)
END_CONNECTION_POINT_MAP()

BEGIN_MSG_MAP(CGame)
	CHAIN_MSG_MAP(CComControl<CGame>)
	DEFAULT_REFLECTION_HANDLER()
	MESSAGE_HANDLER(WM_TIMER, OnTimer)
	MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
	MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
	MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
	MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
	MESSAGE_HANDLER(WM_PAINT, OnPaint)
	MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
	MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
END_MSG_MAP()
// Handler prototypes:
//  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);



// IViewObjectEx
	DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

// IGame
public:
	STDMETHOD(get_TileExtendedCollisions)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(put_TileExtendedCollisions)(/*[in]*/ BOOL newVal);
	STDMETHOD(SpriteSetCollisionSprites)(long lSpriteNum, VARIANT *arrCollisionSprites);
	STDMETHOD(get_SpriteCollisionAccuracy)(long lSpriteNum, /*[out, retval]*/ short *pVal);
	STDMETHOD(put_SpriteCollisionAccuracy)(long lSpriteNum, /*[in]*/ short newVal);
	STDMETHOD(get_DrawHwndControl)(/*[out, retval]*/ DWORD *pVal);
	STDMETHOD(get_SpriteDirectionRate)(long lSpriteNum, /*[out, retval]*/ short *pVal);
	STDMETHOD(put_SpriteDirectionRate)(long lSpriteNum, /*[in]*/ short newVal);
	STDMETHOD(SpriteFrameMirror)(long lSpriteNum);
	STDMETHOD(SpriteFrameMirrorInternal)(long lSpriteNum, BOOL bMirror);
	STDMETHOD(SpriteFrameFlip)(long lSpriteNum);
	STDMETHOD(SpriteCopyFrame)(long lSrcSpriteNum, int lSrcFrame, long lDestSpriteNum, int lDestFrame);
	STDMETHOD(TileSetCollisionTiles)(VARIANT*  arrCollisionTiles);
	STDMETHOD(get_DrawBackgroundShouldScroll)(long lSpriteNum, int iDirection, /*[out, retval]*/ BOOL *pVal);
	STDMETHOD(DrawFullScreen)(BOOL bShowTaskBar, BOOL bShowSIP, BOOL bShowStartIcon);
	STDMETHOD(DrawSetPixelSprite)(long lSpriteNum, int x, int y, BOOL bErase);
	STDMETHOD(TextDisplaySprite)(long lSpriteNum, BSTR bstrString, int lX, int lY, BOOL bTransparent, BOOL bErase);
	STDMETHOD(DrawRectangle)(int x1, int y1, int x2, int y2, BOOL bDrawBackground);
	STDMETHOD(DrawLine)(int x1, int y1, int x2, int y2, int iWidth, BOOL bDrawBackground);
	STDMETHOD(DoInit)();
	STDMETHOD(ScriptRaiseMessage)(BSTR sMessage);
	STDMETHOD(SpriteStretch)(long lSpriteNum, long lWidth, long lHeight);
	STDMETHOD(get_DrawHwnd)(/*[out, retval]*/ DWORD *pVal);
	STDMETHOD(put_DrawHwnd)(/*[in]*/ DWORD newVal);
	STDMETHOD(get_AppPath)(/*[out, retval]*/ BSTR *pVal);
	STDMETHOD(put_AppPath)(/*[in]*/ BSTR newVal);
	STDMETHOD(ScriptStop)();
	STDMETHOD(UtilSleep)(long lMilliseconds);
	STDMETHOD(ScriptExecute)(BSTR sScript);
	STDMETHOD(DrawBackgroundScrollSetOffsets)(int iOffsetX, int iOffSetY);
	STDMETHOD(SoundDelete)(long lSoundNum);
	STDMETHOD(SpriteCopy)(long lSrcSpriteNum, long lDestSpriteNum);
	STDMETHOD(get_SpriteTileCollisionsOn)(long lSpriteNum, /*[out, retval]*/ BOOL *pVal);
	STDMETHOD(put_SpriteTileCollisionsOn)(long lSpriteNum, /*[in]*/ BOOL newVal);
	STDMETHOD(SoundStopLoop)(long lSoundNum);
	STDMETHOD(SoundPlayLoop)(long lSoundNum);
	STDMETHOD(get_InputFireMouseCollisions)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(put_InputFireMouseCollisions)(/*[in]*/ BOOL newVal);
	STDMETHOD(TimerDefineCustom)(int iTimerNum, int iDelay, BOOL bRepeat);
	static int __cdecl ZOrderCompare( const void *arg1, const void *arg2 );
	STDMETHOD(get_SpriteZOrder)(long lSpriteNum, /*[out, retval]*/ short *pVal);
	STDMETHOD(put_SpriteZOrder)(long lSpriteNum, /*[in]*/ short newVal);
	STDMETHOD(UtilMemoryStatus)(/*[in, out]*/ VARIANT *iMemoryLoad, /*[in, out]*/ VARIANT *lTotalPhysicalBytes, /*[in, out]*/ VARIANT *lAvailablePhysicalBytes, /*[in, out]*/ VARIANT *lTotalVirtualBytes, /*[in, out]*/ VARIANT *lAvailableVirtualBytes);
	STDMETHOD(get_UtilRandom)(long lMinVal, long lMaxVal, /*[out, retval]*/ long *pVal);
	STDMETHOD(get_SpriteFrame)(long lSpriteNum, /*[out, retval]*/ int *pVal);
	STDMETHOD(put_SpriteFrame)(long lSpriteNum, /*[in]*/ int newVal);
	STDMETHOD(get_SpriteOnScreen)(long lSpriteNum, /*[out, retval]*/ BOOL *pVal);
	STDMETHOD(SpriteGetPositionEx)(long lSpriteNum, int iOffset, /*[in, out]*/ VARIANT *lX, /*[in, out]*/ VARIANT *lY);
	STDMETHOD(get_SpriteActive)(long lSpriteNum, /*[out, retval]*/ BOOL *pVal);
	STDMETHOD(put_SpriteActive)(long lSpriteNum, /*[in]*/ BOOL newVal);
	STDMETHOD(SpriteGetPosition)(long lSpriteNum, /*[in, out]*/ VARIANT *lX, /*[in, out]*/ VARIANT *lY);
	STDMETHOD(DrawGetDimensions)(/*[in, out]*/ VARIANT *width, /*[in, out]*/ VARIANT *height);
	STDMETHOD(get_TileSpriteCanMove)(long lSpriteNum, int iAngle, int iVelocity, /*[out, retval]*/ BOOL *pVal);
	STDMETHOD(SpriteDiminishCollisionRect)(long lSpriteNum, int iDiminishX, int iDiminishY);
	STDMETHOD(get_TileCausesCollision)(int iTileNum, /*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_TileAtPositionXY)(int lX, int lY, /*[out, retval]*/ short *pVal);
	STDMETHOD(get_TileAtPosition)(int iXMapOffset, int iYMapOffset, /*[out, retval]*/ short *pVal);
	STDMETHOD(put_TileAtPosition)(int iXMapOffset, int iYMapOffset, /*[in]*/ short newVal);
	STDMETHOD(SpriteDelete)(long lSpriteNum);
	STDMETHOD(TileSetMap)(long lSpriteNum, VARIANT*  arrMap, VARIANT*  arrCollisionTiles);
	STDMETHOD(DrawBackgroundScrollGetOffsets)(/*[in, out]*/ VARIANT *iOffsetX, /*[in, out]*/ VARIANT *iOffsetY);
	STDMETHOD(DrawBackgroundScroll)(int iAngle, int iDistance);
	STDMETHOD(DrawBackgroundSprite)(long lSpriteNum, int lX, int lY);
	STDMETHOD(DrawRedrawBackground)(int x, int y, int width, int height);
	STDMETHOD(TextGetDimensions)(BSTR sText, /*[in, out]*/ VARIANT *width, /*[in, out]*/ VARIANT *height);
	STDMETHOD(TextSetAttributes)(BSTR sFaceName, long lPoints, long lWeight, BOOL bItalic, BOOL bUnderline, BOOL bStrikeOut, short iCharSet);
	STDMETHOD(SpriteGetFrameRange)(long lSpriteNum, /*[in, out]*/ VARIANT *iFirstFrame, /*[in, out]*/ VARIANT *iLastFrame, /*[in, out]*/ VARIANT *bLoopFrames);
	STDMETHOD(SpriteSetFrameRange)(long lSpriteNum, int iFirstFrame, int iLastFrame, BOOL bLoopFrames);
	STDMETHOD(SpriteSetPrevFrame)(long lSpriteNum);
	STDMETHOD(TimerPauseTimer)(BOOL bPause);
	STDMETHOD(get_SpriteFrameRate)(long lSpriteNum, /*[out, retval]*/ short *pVal);
	STDMETHOD(put_SpriteFrameRate)(long lSpriteNum, /*[in]*/ short newVal);
	STDMETHOD(get_SpriteAutoDisplay)(long lSpriteNum, /*[out, retval]*/ BOOL *pVal);
	STDMETHOD(put_SpriteAutoDisplay)(long lSpriteNum, /*[in]*/ BOOL newVal);
	STDMETHOD(get_DrawAutoFlipBackBuffer)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(put_DrawAutoFlipBackBuffer)(/*[in]*/ BOOL newVal);
	STDMETHOD(SpriteGetDirection)(long lSpriteNum, /*[in, out]*/ VARIANT *iAngle, /*[in, out]*/ VARIANT *iVelocity);
	STDMETHOD(get_InputKeyDirection)(/*[out, retval]*/ short *pVal);
	
	CGame *m_this;

	 
	// NAG MSG
	BOOL m_bNagged;

	BSTR m_sAppPath;

	
	// # of sprites
	long m_lNumSprites;
	// # of sounds
	long m_lNumSounds;

	// should we check for mouse collisions?
	BOOL m_bFireMouseCollisions;


	// DisplayOrder, used for ZOrdering - contains spritenums in display order
	long m_lDisplayOrder[MAX_DYNAMIC_SPRITES];

	// Key input booleans, true if down
	BOOL m_bInputKeyUp;
	BOOL m_bInputKeyDown;
	BOOL m_bInputKeyLeft;
	BOOL m_bInputKeyRight;
	BOOL m_bInputKeyA;
	BOOL m_bInputKeyB;
	BOOL m_bInputKeyC;
	BOOL m_bInputKeyStart;
	BOOL m_bInputKeyAux1;
	BOOL m_bInputKeyAux2;
	// boundaries of activex control
	RECT m_rcBounds;
	int m_iBoundsWidth;
	int m_iBoundsHeight;
	// should we flip the back buffer after timer?
	BOOL m_bAutoFlipBackBuffer;
	// should we fire timer events?
	BOOL m_bPaused;
	// size of custom background (if scrolling)
	int m_iScrollWidth, m_iScrollHeight;
	// store offset of background for scrolling
	float m_iScrollOffsetX, m_iScrollOffsetY;
	// tiles: array of collision tiles
	BOOL m_bCheckTileCollisions;
	short m_iTiles[MAX_TILES_X][MAX_TILES_Y];
	int m_iNumTilesX, m_iNumTilesY, m_iNumTilesCollision;
	short m_iTilesCollision[MAX_TILES_COLLISION];
	short m_iTileWidth, m_iTileHeight;
	// draw colors
	short	m_DrawRed, m_DrawGreen, m_DrawBlue;
	short	m_DrawBackRed, m_DrawBackGreen, m_DrawBackBlue;
	short	m_DrawTransRed, m_DrawTransGreen, m_DrawTransBlue;
	
	// A double buffer to draw to
	HDC			m_hdc;
	CImageHigh		*m_sprDoubleBuffer;
	// A background buffer used by sprites for "erasing" themselves
	CImageHigh		*m_sprBackground;
	// An optional image to display
	CImageHigh		*m_sprBackgroundImage;

	HWND	m_hwnd;

	GXDisplayProperties m_gxdp;

	// Generic Key List
	GXKeyList m_gxKeys;

	// Sounds
	CWaveOut *sndWaves[MAX_SOUNDS];

	// Our sprites
	CSpriteHigh *m_sprDynamic[MAX_DYNAMIC_SPRITES];


	// Current FONT attributes
	LOGFONT m_lfStyle;



	// Timers
	CTimerCustom *m_tmrCustom[MAX_TIMERS];
	int m_iNumTimers;

	// Timing vars
	unsigned long m_lTimeLastFlipBackBuffer;
	long m_lLastFrameTime;	

	// last mouse position
	int m_MouseX, m_MouseY;

	// Sprite to use for tile set
	long m_lSpriteNumTiles;

	// DrawFullScreen parms
	BOOL m_bNeedFullScreenRefresh;
	BOOL m_bAutoFullScreen;
	BOOL m_bShowTaskBar;
	BOOL m_bShowSIP;
	BOOL m_bShowStartIcon;

	BOOL m_bInitialized;

	BOOL m_bTileExtendedCollisions;
    short m_bTileCollisionsX[3];
    short m_bTileCollisionsY[3];
	short m_bTileCollisionsTileNum[3];
	short m_bTileNumCollisions;
	
	STDMETHOD(get_InputKeyAux2)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyAux1)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyStart)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyC)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyB)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyA)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyRight)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyLeft)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyDown)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_InputKeyUp)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(get_UtilGetAngleBetween)(int x1, int y1, int x2, int y2, /*[out, retval]*/ short *pVal);
	STDMETHOD(SpriteSetDirection)(long lSpriteNum, int iAngle, int iVelocity);
	STDMETHOD(DrawGetPixel)(int x, int y, VARIANT *red, VARIANT *green, VARIANT *blue);
	STDMETHOD(SoundPlay)(long lSoundNum);
	STDMETHOD(SoundLoad)(long lSoundNum, BSTR sFileName);
	STDMETHOD(get_TimerGetFrameRate)(/*[out, retval]*/ long *pVal);
	STDMETHOD(get_TimerGetTickCount)(/*[out, retval]*/ long *pVal);
	STDMETHOD(DrawBackgroundImage)(BSTR sFileName, int lX, int lY);
	STDMETHOD(SpriteSetPosition)(long lSpriteNum, long lX, long lY);
	STDMETHOD(SpriteSetNextFrame)(long lSpriteNum);
	STDMETHOD(DrawSetTransparentColor)(int red, int green, int blue);
	STDMETHOD(SpriteDisplay)(long lSpriteNum);
	STDMETHOD(DrawFlipBackBuffer)();
	STDMETHOD(SpriteDefine)(long lSpriteNum, BSTR sFileName, long iXPosBMP, long iYPosBMP, long iFrameWidth, long iFrameHeight, long iFrameCount, long iFramesPerRow);
	STDMETHOD(DrawSetBackColor)(int red, int green, int blue);
	void MessageError(LPTSTR lpStr);
	LRESULT EventHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
	STDMETHOD(DrawSetDrawColor)(int red, int green, int blue);
	STDMETHOD(TextDisplay)(BSTR bstrString, int lX, int lY, BOOL bTransparent, BOOL bDrawBackground);
	STDMETHOD(DrawSetPixel)(int x, int y, BOOL bDrawBackground);
	STDMETHOD(DrawFloodFill)();
	STDMETHOD(DrawDisable)();
	STDMETHOD(DrawInit)(DWORD hwnd, int iCustomWidth, int iCustomHeight);
	STDMETHOD(TimerStopTimer)();
	STDMETHOD(TimerStartTimer)(long lMilliseconds);

	LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	
	LRESULT OnKeyUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);


	HRESULT OnDraw(ATL_DRAWINFO& di)
	{
		m_rcBounds = *(RECT*)di.prcBounds;
		m_iBoundsHeight = m_rcBounds.bottom - m_rcBounds.top;
		m_iBoundsWidth = m_rcBounds.right - m_rcBounds.left;

		// Give the nag message
		
		//if (!m_bNagged) {
		//	m_bNagged = TRUE;
		//	MessageBox(_T("Thank you for beta testing ASpriteCE 1.0.05. For problem reporting, visit www.spritehand.com\n\nClick Ok To Continue."),
		//	_T("ASpriteCE Trial"), MB_OK);
		//}
		

		return S_OK;
	}
private:
	void DoZorder();
};

#endif //__Game_H_
